#include <QPushButton>
#include <QAction>
#include "vtkwidget.h"


//#include <sstream>

#include <vtkPolyDataMapper.h>
#include <vtkPolyDataReader.h>
#include <vtkProperty.h>
//#include <vtkClipPolyData.h>
//#include <vtkPolyDataConnectivityFilter.h>
#include <vtkIdList.h>
#include <vtkVertexGlyphFilter.h>
//#include <vtkCollectionIterator.h>

/*
extern QAction *actionShowBox;
extern QAction *actionBoxClip;
extern QAction *actionPlaneClip;
extern QAction *actionUndo;
extern QAction *actionAccept;
extern QAction *actionWireOn;
extern QPushButton *btnSB;
extern QPushButton *btnBC;
extern QPushButton *btnPC;
extern QPushButton *btnUD;
extern QPushButton *btnAC;
extern QPushButton *btnWO;
*/

VTKWidget::VTKWidget(QWidget * parent) : QWidget(parent)
{
	m_renWin = vtkSmartPointer<vtkRenderWindow>::New();
	m_renWin->SetParentId(this->winId());	

	m_actor = vtkSmartPointer<vtkActor>::New();
	f_actor = vtkSmartPointer<vtkActor>::New();
	
	m_ren1= vtkSmartPointer<vtkRenderer>::New();
	//ren2= vtkRenderer::New();
	
	m_ren1->SetBackground( 0, 0, 0 );
	//ren2->SetBackground(0,0,0);

	m_renWin->AddRenderer( m_ren1 );	
	//renWin->AddRenderer( ren2 );
	

	m_iren=vtkSmartPointer<vtkRenderWindowInteractor>::New();
	m_iren->SetRenderWindow(m_renWin);	

	m_style=vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
	m_iren->SetInteractorStyle(m_style);
	isWire = 0;

	
	m_renWin->Render();
}

void VTKWidget::mouseReleaseEvent(QMouseEvent* event)
{
	//util->log("notified");
}


void VTKWidget::renderModel(const char * path)
{
	vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName(path);
	m_data_hybroid = reader->GetOutput();
	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInput(m_data_hybroid);
	m_actor->SetMapper( mapper );
	//actor->SetOrientation(90,0,0);
	//actor->RotateX(90);
	//boxClipActor->RotateX(90);
	//planeClipActor->RotateX(90);
	//planeClipRestActor->RotateX(90);

	m_ren1->AddActor( m_actor );
	//ren1->AddActor(clip_actor);
	//util->log(cube->GetXPlusFaceText());
	//ren1->SetViewPoint(-1,-1,-1);
	//ren1->GetActiveCamera()->Zoom(0.1);
	//renWin->AddRenderer( ren1 );
	m_iren->Initialize();
	m_ren1->ResetCamera();
	m_ren1->GetActiveCamera()->Zoom(1);

	//
	// Start the event loop.

	m_renWin->Render();
}

void VTKWidget::initHybroid(hybroid* h, int R, int G, int B)
{
	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	node *p, *nds = h->nodes;
	int ni = 0;
	vector auxpos;

	//float force_factor = 5000;
	//
	//vtkFloatArray *vectors = vtkFloatArray::New();
	//vectors->SetNumberOfComponents(3);
	//vectors->SetNumberOfTuples(h->numnodes);
	//
	//float force[3];


	for(p = nds; ni < h->numnodes; p++, ni++)
	{
		vminus(p->posit, h->translation, auxpos);
		vscale(1.008, auxpos, auxpos);
		vplus(auxpos, h->translation, auxpos);
		points->InsertNextPoint(auxpos.x, auxpos.y, auxpos.z);

		//force[0] = p->force.x;force[1] = p->force.y;force[2] = p->force.z;
		//force[0] = force[0]* force_factor;
		//force[1] = force[1]* force_factor;
		//force[2] = force[2]* force_factor;
		//vectors->InsertNextTuple(force);

	}

	m_data_hybroid = vtkSmartPointer<vtkPolyData>::New();
	m_data_hybroid->SetPoints(points);
	m_data_hybroid->Allocate();

	//m_data_hybroid->GetPointData()->SetVectors(vectors);


	int l, j, k;
	int numelms = h->numelems;
	vtkIdType pts[3] = {0};
	elem *elmi, *elms = h->elems;
	for (l = 0; l < numelms; l++) {
		elmi = &elms[l];
		for (j = 0; j < elmi->nomnodes; j++) {
			pts[j] = elmi->vertices[j]->node_id;
		}
		m_data_hybroid->InsertNextCell(VTK_TRIANGLE, 3, pts);
	}

	//vtkHedgeHog *hedgehog = vtkHedgeHog::New();
	//hedgehog->SetInput(m_data_hybroid);
	//hedgehog->SetScaleFactor(1);

	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInput(m_data_hybroid);
	m_actor->SetMapper(mapper);
	m_actor->GetProperty()->SetColor(R/255, G/255, B/255);
	m_actor->GetProperty()->SetOpacity(0.5);
	m_actor->GetProperty()->SetPointSize(10);
	//m_actor->GetProperty()->SetEdgeColor(1,0,0);
	m_ren1->AddActor( m_actor );
	m_ren1->ResetCamera();
	m_ren1->GetActiveCamera()->Zoom(1);
}

void VTKWidget::initForce(hybroid* h, int R, int G, int B)
{
	//vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	node *p, *nds = h->nodes;
	vector auxpos;
	int ni = 0;
	

	float force_factor = 5000;
	
	vtkFloatArray *vectors = vtkFloatArray::New();
	vectors->SetNumberOfComponents(3);
	vectors->SetNumberOfTuples(h->numnodes);
	
	float force[3];


	for(p = nds; ni < h->numnodes; p++, ni++)
	{
		//vminus(p->posit, h->translation, auxpos);
		//vscale(1.008, auxpos, auxpos);
		//vplus(auxpos, h->translation, auxpos);
		//points->InsertNextPoint(auxpos.x, auxpos.y, auxpos.z);

		force[0] = p->force.x;force[1] = p->force.y;force[2] = p->force.z;
		force[0] = force[0]* force_factor;
		force[1] = force[1]* force_factor;
		force[2] = force[2]* force_factor;
		vectors->InsertNextTuple(force);

	}

	//m_data_hybroid = vtkSmartPointer<vtkPolyData>::New();
	//m_data_hybroid->SetPoints(points);
	//m_data_hybroid->Allocate();

	m_data_hybroid->GetPointData()->SetVectors(vectors);


	//int l, j, k;
	//int numelms = h->numelems;
	//vtkIdType pts[3] = {0};
	//elem *elmi, *elms = h->elems;
	//for (l = 0; l < numelms; l++) {
	//	elmi = &elms[l];
	//	for (j = 0; j < elmi->nomnodes; j++) {
	//		pts[j] = elmi->vertices[j]->node_id;
	//	}
	//	m_data_hybroid->InsertNextCell(VTK_TRIANGLE, 3, pts);
	//}

	vtkHedgeHog *hedgehog = vtkHedgeHog::New();
	hedgehog->SetInput(m_data_hybroid);
	hedgehog->SetScaleFactor(1);

	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInput(hedgehog->GetOutput());
	f_actor->SetMapper(mapper);
	f_actor->GetProperty()->SetColor(R/255, G/255, B/255);
	m_ren1->AddActor( f_actor );
	m_ren1->ResetCamera();
	m_ren1->GetActiveCamera()->Zoom(1);
}

void VTKWidget::renderHybroid(hybroid* h, int R, int G, int B)
{
	vtkSmartPointer<vtkPoints> points;
	node *p, *nds = h->nodes;
	vector auxpos;

	//vtkFloatArray *vectors = vtkFloatArray::New();
	//vectors->SetNumberOfComponents(3);
	//vectors->SetNumberOfTuples(h->numnodes);
	//
	//float force[3];
	//float force_factor = 5000;

	if(h->numnodes != m_data_hybroid->GetNumberOfPoints()){
		points = vtkSmartPointer<vtkPoints>::New();
		int ni = 0;
		
		for(p = nds; ni < h->numnodes; p++, ni++)
		{
			vminus(p->posit, h->translation, auxpos);
			vscale(1.008, auxpos, auxpos);
			vplus(auxpos, h->translation, auxpos);
			points->InsertNextPoint(auxpos.x, auxpos.y, auxpos.z);

			//force[0] = p->force.x;force[1] = p->force.y;force[2] = p->force.z;
			//printf("%f,%f,%f\n",p->force.x,p->force.y,p->force.z);
			//force[0] = force[0]* force_factor;
			//force[1] = force[1]* force_factor;
			//force[2] = force[2]* force_factor;
			//vectors->InsertNextTuple(force);
		}

		m_data_hybroid = vtkSmartPointer<vtkPolyData>::New();
		m_data_hybroid->SetPoints(points);
		m_data_hybroid->Allocate();

		
		//m_data_hybroid->GetPointData()->SetVectors(vectors);

		int l, j, k;
		int numelms = h->numelems;
		vtkIdType pts[3] = {0};
		elem *elmi, *elms = h->elems;
		for (l = 0; l < numelms; l++) {
			elmi = &elms[l];
			for (j = 0; j < elmi->nomnodes; j++) {
				pts[j] = elmi->vertices[j]->node_id;
			}
			m_data_hybroid->InsertNextCell(VTK_TRIANGLE, 3, pts);
		}

		//vtkHedgeHog *hedgehog = vtkHedgeHog::New();
		//hedgehog->SetInput(m_data_hybroid);
		//hedgehog->SetScaleFactor(100);

		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInput(m_data_hybroid);
		m_actor->SetMapper(mapper);
		m_actor->GetProperty()->SetPointSize(3);
		m_actor->GetProperty()->SetColor(R/255, G/255, B/255);
		m_actor->GetProperty()->SetOpacity(0.5);
		m_actor->GetProperty()->SetPointSize(10);
		//m_actor->GetProperty()->SetEdgeColor(1,0,0);
		m_ren1->AddActor( m_actor );
	}
	else{
		points = m_data_hybroid->GetPoints();
		int ni = 0;
		
		for(p = nds; ni < h->numnodes; p++, ni++)
		{
			vminus(p->posit, h->translation, auxpos);
			vscale(1.008, auxpos, auxpos);
			vplus(auxpos, h->translation, auxpos);
			points->SetPoint(ni, auxpos.x, auxpos.y, auxpos.z);

			//force[0] = p->force.x;force[1] = p->force.y;force[2] = p->force.z;
			//
			//force[0] = force[0]* force_factor;
			//force[1] = force[1]* force_factor;
			//force[2] = force[2]* force_factor;
			//printf("%f,%f,%f\n",force[0],force[1],force[2]);
			//vectors->SetTupleValue(ni, force);
		}
		m_data_hybroid->Modified();
		//m_data_hybroid->GetPointData()->SetVectors(vectors);
	}

	//m_ren1->ResetCamera();
	//m_ren1->GetActiveCamera()->Zoom(1);
	m_renWin->Render();
}


void VTKWidget::initRangeData(hybroid* h, int R, int G, int B)
{
	range_datapoint *p;

	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();

	p = h->range_data;
	for (int i = 0; i < h->numdatapoints; i++)
	{
		points->InsertNextPoint(p->position.x, p->position.y, p->position.z);
		p++;
	}
 
	m_range_data = vtkSmartPointer<vtkPolyData>::New();
	m_range_data->SetPoints(points);
 
	vtkSmartPointer<vtkVertexGlyphFilter> vertexGlyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
	vertexGlyphFilter->AddInput(m_range_data);
	vertexGlyphFilter->Update();
 
	// Create a mapper and actor
	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(vertexGlyphFilter->GetOutputPort());
 
	vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);
	actor->GetProperty()->SetPointSize(3);
	actor->GetProperty()->SetColor(R/255, G/255, B/255);

	m_ren1->AddActor(actor);

	m_iren->Initialize();
	m_ren1->ResetCamera();
	m_ren1->GetActiveCamera()->Zoom(1);
}

void VTKWidget::renderRangeData(hybroid* h, int R, int G, int B)
{
	range_datapoint *p;

	vtkSmartPointer<vtkPoints> points = m_range_data->GetPoints();

	p = h->range_data;
	for (int i = 0; i < h->numdatapoints; i++)
	{
		points->SetPoint(i, p->position.x, p->position.y, p->position.z);
		p++;
	}

	m_range_data->Modified();
 
	//m_ren1->ResetCamera();
	//m_ren1->GetActiveCamera()->Zoom(1);

	m_renWin->Render();
}

void VTKWidget::renderForces(hybroid* h, int R, int G, int B)
{
	//vtkSmartPointer<vtkPoints> points;
	node *p, *nds = h->nodes;
	vector auxpos;

	vtkFloatArray *vectors = vtkFloatArray::New();
	vectors->SetNumberOfComponents(3);
	vectors->SetNumberOfTuples(h->numnodes);
	
	float force[3];
	float force_factor = 5000;

	if(h->numnodes != m_data_hybroid->GetNumberOfPoints()){
		//points = vtkSmartPointer<vtkPoints>::New();
		int ni = 0;
		
		for(p = nds; ni < h->numnodes; p++, ni++)
		{
			//vminus(p->posit, h->translation, auxpos);
			//vscale(1.008, auxpos, auxpos);
			//vplus(auxpos, h->translation, auxpos);
			//points->InsertNextPoint(auxpos.x, auxpos.y, auxpos.z);

			force[0] = p->force.x;force[1] = p->force.y;force[2] = p->force.z;
			//printf("%f,%f,%f\n",p->force.x,p->force.y,p->force.z);
			force[0] = force[0]* force_factor;
			force[1] = force[1]* force_factor;
			force[2] = force[2]* force_factor;
			vectors->InsertNextTuple(force);
		}

		//m_data_hybroid = vtkSmartPointer<vtkPolyData>::New();
		//m_data_hybroid->SetPoints(points);
		//m_data_hybroid->Allocate();

		
		m_data_hybroid->GetPointData()->SetVectors(vectors);

		//int l, j, k;
		//int numelms = h->numelems;
		//vtkIdType pts[3] = {0};
		//elem *elmi, *elms = h->elems;
		//for (l = 0; l < numelms; l++) {
		//	elmi = &elms[l];
		//	for (j = 0; j < elmi->nomnodes; j++) {
		//		pts[j] = elmi->vertices[j]->node_id;
		//	}
		//	m_data_hybroid->InsertNextCell(VTK_TRIANGLE, 3, pts);
		//}

		vtkHedgeHog *hedgehog = vtkHedgeHog::New();
		hedgehog->SetInput(m_data_hybroid);
		hedgehog->SetScaleFactor(100);

		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInput(hedgehog->GetOutput());
		f_actor->SetMapper(mapper);
		f_actor->GetProperty()->SetPointSize(3);
		f_actor->GetProperty()->SetColor(R/255, G/255, B/255);
		m_ren1->AddActor( f_actor );
	}
	else{
		//points = m_data_hybroid->GetPoints();
		int ni = 0;
		
		for(p = nds; ni < h->numnodes; p++, ni++)
		{
			//vminus(p->posit, h->translation, auxpos);
			//vscale(1.008, auxpos, auxpos);
			//vplus(auxpos, h->translation, auxpos);
			//points->SetPoint(ni, auxpos.x, auxpos.y, auxpos.z);

			force[0] = p->force.x;force[1] = p->force.y;force[2] = p->force.z;
			
			force[0] = force[0]* force_factor;
			force[1] = force[1]* force_factor;
			force[2] = force[2]* force_factor;
			//printf("%f,%f,%f\n",force[0],force[1],force[2]);
			vectors->SetTupleValue(ni, force);
		}
		//m_data_hybroid->Modified();
		m_data_hybroid->GetPointData()->SetVectors(vectors);
	}

	//m_ren1->ResetCamera();
	//m_ren1->GetActiveCamera()->Zoom(1);
	m_renWin->Render();
}

vtkCamera* VTKWidget::getActiveCamera() 
{
	return m_ren1->GetActiveCamera();
}

VTKWidget::~VTKWidget() {

}


void VTKWidget::setSize(int width, int height) {

	m_renWin->SetSize(width,height);
}

void VTKWidget::resizeEvent ( QResizeEvent * event ) {

	m_renWin->SetSize(width(), height());
}

void VTKWidget::mouseMoveEvent(QMouseEvent * event) 
{
	m_style->OnMouseMove();
	if(event->button() == Qt::LeftButton )
	{
		
	}

}

void VTKWidget::onFrontbutton()
{
	vtkCamera* camera=m_ren1->GetActiveCamera();
	camera->SetFocalPoint(0,0,0);
	camera->SetPosition(0,0,600);
	camera->SetViewUp(0,1,0);
	camera->ParallelProjectionOn();
	m_ren1->ResetCamera();
	
}
void VTKWidget::onBackbutton()
{
	vtkCamera* camera=m_ren1->GetActiveCamera();
	camera->SetFocalPoint(0,0,0);
	camera->SetPosition(0,0,-600);
	camera->SetViewUp(0,1,0);
	camera->ParallelProjectionOn();
	m_ren1->ResetCamera();

}
void VTKWidget::onLeftbutton()
{
	vtkCamera* camera=m_ren1->GetActiveCamera();
	camera->SetFocalPoint(0,0,0);
	camera->SetPosition(-600,0,0);
	camera->SetViewUp(0,1,0);
	camera->ParallelProjectionOn();
	m_ren1->ResetCamera();

}
void VTKWidget::onRightbutton()
{
	vtkCamera* camera=m_ren1->GetActiveCamera();
	camera->SetFocalPoint(0,0,0);
	camera->SetPosition(600,0,0);
	camera->SetViewUp(0,1,0);
	camera->ParallelProjectionOn();
	m_ren1->ResetCamera();

}
void VTKWidget::onTopbutton()
{
	vtkCamera* camera=m_ren1->GetActiveCamera();
	camera->SetFocalPoint(0,0,0);
	camera->SetPosition(0,600,0);
	camera->SetViewUp(0,0,-1);
	camera->ParallelProjectionOn();
	m_ren1->ResetCamera();

}
void VTKWidget::onBottombutton()
{
	vtkCamera* camera=m_ren1->GetActiveCamera();
	camera->SetFocalPoint(0,0,0);
	camera->SetPosition(0,-600,0);
	camera->SetViewUp(0,0,1);
	camera->ParallelProjectionOn();
	m_ren1->ResetCamera();

}


void VTKWidget::wireOnOff()
{
	isWire = !isWire;
	if (isWire) {
		{
			m_actor->GetProperty()->SetRepresentationToWireframe();
			m_actor->Modified();
		}
		emit setWire(true);
	}
	else {

		{
			m_actor->GetProperty()->SetRepresentationToSurface();
			m_actor->Modified();
		}

		emit setWire(false);
	}
	
	m_renWin->Render();
}

